Load the lib (you might want to install it first).

library(bibliometrix)   ### load bibliometrix package
Please note that our software is open source and available for use, distributed under the MIT license.
When it is used in a publication, we ask that authors properly cite the following reference:

Aria, M. & Cuccurullo, C. (2017) bibliometrix: An R-tool for comprehensive science mapping analysis, 
                        Journal of Informetrics, 11(4), pp 959-975, Elsevier.

Failure to properly cite the software is considered a violation of the license.
                        
For information and bug reports:
                        - Take a look at https://www.bibliometrix.org
                        - Send an email to info@bibliometrix.org   
                        - Write a post on https://github.com/massimoaria/bibliometrix/issues
                        
Help us to keep Bibliometrix and Biblioshiny free to download and use by contributing with a small donation to support our research team (https://bibliometrix.org/donate.html)

                        
To start with the Biblioshiny app, please digit:
biblioshiny()
library(htmlwidgets) # to have saveWidget
library(data.table) # for the sources tables
data.table 1.14.10 using 8 threads (see ?getDTthreads).  Latest news: r-datatable.com

Import the wos and scopus publication files.

file_wos <- "wos_2018_2023.bib"
file_scopus <- "scopus_2018_2024.bib"
M_wos <- convert2df(file = file_wos, dbsource = "wos", format = "bibtex")

Converting your wos collection into a bibliographic dataframe

Done!


Generating affiliation field tag AU_UN from C1:  Done!
M_scopus <- convert2df(file = file_scopus, dbsource = "scopus", format = "bibtex")

Converting your scopus collection into a bibliographic dataframe


Warning:
In your file, some mandatory metadata are missing. Bibliometrix functions may not work properly!

Please, take a look at the vignettes:
- 'Data Importing and Converting' (https://www.bibliometrix.org/vignettes/Data-Importing-and-Converting.html)
- 'A brief introduction to bibliometrix' (https://www.bibliometrix.org/vignettes/Introduction_to_bibliometrix.html)


Missing fields:  CR 
Done!


Generating affiliation field tag AU_UN from C1:  Done!


Removed  9 duplicated documents

First bibliometric analysis:

results_wos <- biblioAnalysis(M_wos, sep = ";")
results_scopus <- biblioAnalysis(M_scopus, sep = ";")
write.csv(results_wos$Sources, "sources_wos.csv", row.names=FALSE)
write.csv(results_scopus$Sources, "sources_scopus.csv", row.names=FALSE)

Basic plots for WoS data.

plot(x = results_wos, k = 10, pause = FALSE)
Avis : Removed 1 rows containing non-finite values (`stat_align()`).

Basic plots for Scopus data.

plot(x = results_scopus, k = 10, pause = FALSE)
Avis : Removed 1 rows containing non-finite values (`stat_align()`).

Some citation analysis with WoS data.

CR <- citations(M_wos, field = "article", sep = ";")
cbind(CR$Cited[1:10])
                                                                                                                                     [,1]
LOWE DG, 2004, INT J COMPUT VISION, V60, P91, DOI 10.1023/B:VISI.0000029664.99615.94                                                   14
RONNEBERGER O, 2015, LECT NOTES COMPUT SC, V9351, P234, DOI 10.1007/978-3-319-24574-4\\_28                                             11
ANONYMOUS, P IEEE C COMP VIS PA                                                                                                        10
INGLADA J, 2017, REMOTE SENS-BASEL, V9, DOI 10.3390/RS9010095                                                                          10
GOODCHILD MF, 2007, GEOJOURNAL, V69, P211, DOI 10.1007/S10708-007-9111-Y                                                                8
MACKANESS W., 2002, P JOINT ISPRSICA WOR, P7                                                                                            8
TOUYA G, 2010, T GIS, V14, P595, DOI 10.1111/J.1467-9671.2010.01215.X                                                                   8
TOUYA G, 2019, INT J CARTOGRAPHY, V5, P142, DOI 10.1080/23729333.2019.1613071                                                           8
COUCLELIS H., 1987, J ENVIRON PSYCHOL, V7, P99, DOI DOI 10.1016/S0272-4944(87)80020-8, HTTPS://DOI.ORG/10.1016/S0272-4944(87)80020-8    7
GIRRES JF, 2010, T GIS, V14, P435, DOI 10.1111/J.1467-9671.2010.01203.X                                                                 7
A <- cocMatrix(M_wos, Field = "SO", sep = ";")
sort(Matrix::colSums(A), decreasing = TRUE)[1:10]
                                      ISPRS INTERNATIONAL JOURNAL OF GEO-INFORMATION 
                                                                                  12 
                                                                      REMOTE SENSING 
                                                                                  12 
                                                INTERNATIONAL JOURNAL OF CARTOGRAPHY 
                                                                                   9 
                        30TH INTERNATIONAL CARTOGRAPHIC CONFERENCE (ICC 2021), VOL 4 
                                                                                   7 
       IGARSS 2018 - 2018 IEEE INTERNATIONAL GEOSCIENCE AND REMOTE SENSING SYMPOSIUM 
                                                                                   7 
                                  ISPRS JOURNAL OF PHOTOGRAMMETRY AND REMOTE SENSING 
                                                                                   7 
                                                       REMOTE SENSING OF ENVIRONMENT 
                                                                                   5 
                                       2019 JOINT URBAN REMOTE SENSING EVENT (JURSE) 
                                                                                   4 
2020 MEDITERRANEAN AND MIDDLE-EAST GEOSCIENCE AND REMOTE SENSING SYMPOSIUM (M2GARSS) 
                                                                                   4 
                           INTERNATIONAL JOURNAL OF GEOGRAPHICAL INFORMATION SCIENCE 
                                                                                   4 
A <- cocMatrix(M_wos, Field = "CR", sep = ".  ")
sort(Matrix::colSums(A), decreasing = TRUE)[1:10]
                                                                                ACHANTA R 2012 IEEE T PATTERN ANAL  
                                                                                                                  2 
                                                                                       ADAMO M 2014 LANDSCAPE ECOL  
                                                                                                                  2 
                                                                              ADHIKARI B 2018 LECT NOTES ARTIF INT  
                                                                                                                  2 
                                                                                ADLER BT 2011 LECT NOTES COMPUT SC  
                                                                                                                  2 
                                                                                           ALI I 2016 J PLANT ECOL  
                                                                                                                  2 
                                                                              ALTAMIMI Z 2016 J GEOPHYS RES-SOL EA  
                                                                                                                  2 
ALVINA J 2014 PROCEEDINGS OF THE 2014 INTERNATIONAL WORKING CONFERENCE ON ADVANCED VISUAL INTERFACES AVI 2014 P125  
                                                                                                                  2 
                                                                                AMAZIRH A 2018 REMOTE SENS ENVIRON  
                                                                                                                  2 
                                                           ANONYMOUS 2006 INT ARCH PHOTOGRAM 3 BOUDET L 2006 IAPRS  
                                                                                                                  2 
                                                                         ANOOSHEH A 2019 IEEE INT CONF ROBOT P5958  
                                                                                                                  2 

The main sources for publication according to WoS data:

data.table(results_wos$Sources)

The main sources for publication according to Scopus data:

data.table(results_scopus$Sources)

Create keyword co-occurrences network with WoS data:

NetMatrix <- biblioNetwork(M_wos, analysis = "co-occurrences", network = "keywords", sep = ";")
# Plot the network
net=networkPlot(NetMatrix, normalize="association", weighted=T, n = 25, Title = "WoS Keyword Co-occurrences", type = "fruchterman", size=T, edgesize = 4,labelsize=1.0,community.repulsion = 0.1,size.cex = T,halo = F)

Create keyword co-occurrences network with Scopus data:

NetMatrix <- biblioNetwork(M_scopus, analysis = "co-occurrences", network = "keywords", sep = ";")
# Plot the network
net=networkPlot(NetMatrix, normalize="association", weighted=T, n = 20, Title = "Scopus Keyword Co-occurrences", type = "fruchterman", size=T, edgesize = 4,labelsize=1.0,community.repulsion = 0.1,size.cex = T,halo = F)

Create classical article coupling network with WoS data:

NetMatrix <- biblioNetwork(M_wos, analysis = "coupling", network = "references", sep = ";")
# Plot the network
net=networkPlot(NetMatrix,  normalize = "salton", weighted=NULL, n = 30, Title = "WoS Article' Coupling", type = "fruchterman", size=10,size.cex=T,remove.multiple=TRUE,labelsize=1.0,label.n=20,label.cex=F)

Create authors’ coupling network with WoS data:

NetMatrix <- biblioNetwork(M_wos, analysis = "coupling", network = "authors", sep = ";")
net=networkPlot(NetMatrix,  normalize = "salton", weighted=T, n = 20, Title = "WoS Authors' Coupling", type = "fruchterman", size = 5,size.cex=T,remove.multiple=TRUE,labelsize=2.0,label.n=20,label.cex = T)

Conceptual Structure using keywords (method=“CA”) with WoS data:

options(ggrepel.max.overlaps = Inf)
CS <- conceptualStructure(M_wos,field="ID", method="CA", minDegree=4, clust=5, stemming=FALSE, labelsize=10, documents=10)

Conceptual Structure using keywords (method=“CA”) with Scopus data:

CS <- conceptualStructure(M_scopus,field="ID", method="CA", minDegree=4, clust=5, stemming=FALSE, labelsize=10, documents=10)

Create a historical citation network with WoS data:

histResults <- histNetwork(M_wos, min.citations = 1, sep = ";")

WOS DB:
Searching local citations (LCS) by reference items (SR) and DOIs...

Analyzing 9716 reference items...

Found 22 documents with no empty Local Citations (LCS)
# Plot a historical co-citation network
options(repr.plot.width = 10, repr.plot.height =20) 
png(filename="histNetwork.png", width=1000, height=1000)
net <- histPlot(histResults, n=50, size = 4, labelsize=4)

 Legend
dev.off()
null device 
          1 
The resulting historical network
The resulting historical network

Read the synonym and ignored keywords files.

#synonyms_file <- read.csv("synonyms.csv")
synonyms_file <- scan("synonyms.csv",sep='\n', what = "", quiet = TRUE)
synonyms_file <- gsub(",", "; ", synonyms_file)
synonyms_file <- c(synonyms_file)
remove_file <- scan("remove.csv",sep='\n', what = "", quiet = TRUE)
remove_file <- remove_file

Now, create the thematic map using the synonyms with WoS data:

res <- thematicMap(M_wos, field = "ID", n = 250, minfreq = 5, size = 0.5, repel = TRUE, synonyms = synonyms_file, remove.terms = remove_file)
plot(res$map)

Now, create the thematic map using the synonyms and the author’s keywords with WoS data:

res <- thematicMap(M_wos, field = "DE", n = 250, minfreq = 5, size = 0.5, repel = TRUE, synonyms = synonyms_file, remove.terms = remove_file)
plot(res$map)

The same but with the Scopus data:

res <- thematicMap(M_scopus, field = "ID", n = 250, minfreq = 5, size = 0.5, repel = TRUE, synonyms = synonyms_file, remove.terms = remove_file)
plot(res$map)

The same but with the Scopus data and the author’s keywords:

res <- thematicMap(M_scopus, field = "DE", n = 250, minfreq = 5, size = 0.5, repel = TRUE, synonyms = synonyms_file, remove.terms = remove_file)
plot(res$map)

We add the function to create wordlists.

wordlist <- function(M, Field, n, measure, ngrams, remove.terms=NULL, synonyms=NULL){
  switch(Field,
         ID={v=tableTag(M,"ID", remove.terms  = remove.terms, synonyms = synonyms)},
         DE={v=tableTag(M,"DE", remove.terms = remove.terms, synonyms = synonyms)},
         TI={
           if (!("TI_TM" %in% names(M))){
             v=tableTag(M,"TI", ngrams=ngrams, remove.terms=remove.terms, synonyms = synonyms)
             
           }},
         AB={if (!("AB_TM" %in% names(M))){
           v=tableTag(M,"AB", ngrams=ngrams, remove.terms = remove.terms, synonyms = synonyms)
         }},
         WC={
           v=tableTag(M,"WC")
         }
  )
  names(v)=tolower(names(v))
  #v=tableTag(values$M,"ID")
  n=min(c(n,length(v)))
  Words=data.frame(Terms=names(v)[1:n], Frequency=(as.numeric(v)[1:n]), stringsAsFactors = FALSE)
  W=Words
  switch(measure,
         identity={},
         sqrt={W$Frequency=sqrt(W$Frequency)},
         log={W$Frequency=log(W$Frequency+1)},
         log10={W$Frequency=log10(W$Frequency+1)}
  )
  
  results=list(v=v,W=W, Words=Words)
  return(results)
}
resW <- wordlist(M=M_wos, Field="ID", n=150, measure="identity", ngrams=1, synonyms = synonyms_file, remove.terms = remove_file)
W <- resW$W
write.csv(resW[["W"]], "data_wos.csv", row.names=FALSE)
Words <- resW$Words
w1 <- wordcloud2::wordcloud2(W, size = 1.5, minRotation = 0, maxRotation = 0, rotateRatio = 1)#minRotation = -pi/2, maxRotation = -pi/2)
saveWidget(w1, 'w1.html', selfcontained = T)

Wordcloud with WoS and keywords plus.

resW <- wordlist(M=M_wos, Field="DE", n=150, measure="identity", ngrams=1, remove.terms = remove_file, synonyms = synonyms_file)
W <- resW$W
write.csv(resW[["W"]], "data_wos_de.csv", row.names=FALSE)
Words <- resW$Words
w2 <- wordcloud2::wordcloud2(W, size = 1.5, minRotation = 0, maxRotation = 0, rotateRatio = 1)#minRotation = -pi/2, maxRotation = -pi/2)
saveWidget(w2, 'w2.html', selfcontained = T)

Wordcloud with WoS and author’s keywords.

resW <- wordlist(M=M_scopus, Field="ID", n=150, measure="identity", ngrams=1, remove.terms = remove_file, synonyms = synonyms_file)
W <- resW$W
write.csv(resW[["W"]], "data_scopus.csv", row.names=FALSE)
Words <- resW$Words
w3 <- wordcloud2::wordcloud2(W, size = 1.5, color = 'random-dark', minRotation = 0, maxRotation = 0, rotateRatio = 1)
saveWidget(w3, 'w3.html', selfcontained = T)

Wordcloud with Scopus and keywords plus.

resW <- wordlist(M=M_scopus, Field="DE", n=150, measure="identity", ngrams=1, remove.terms = remove_file, synonyms = synonyms_file)
W <- resW$W
write.csv(resW[["W"]], "data_scopus_de.csv", row.names=FALSE)
Words <- resW$Words
w4 <- wordcloud2::wordcloud2(W, size = 1.5, color = 'random-dark', minRotation = 0, maxRotation = 0, rotateRatio = 1)
saveWidget(w4, 'w4.html', selfcontained = T)

Wordcloud with Scopus and author’s keywords.

We are done!

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKTG9hZCB0aGUgbGliICh5b3UgbWlnaHQgd2FudCB0byBpbnN0YWxsIGl0IGZpcnN0KS4KCmBgYHtyfQpsaWJyYXJ5KGJpYmxpb21ldHJpeCkgICAjIyMgbG9hZCBiaWJsaW9tZXRyaXggcGFja2FnZQpsaWJyYXJ5KGh0bWx3aWRnZXRzKSAjIHRvIGhhdmUgc2F2ZVdpZGdldApsaWJyYXJ5KGRhdGEudGFibGUpICMgZm9yIHRoZSBzb3VyY2VzIHRhYmxlcwpgYGAKCkltcG9ydCB0aGUgd29zIGFuZCBzY29wdXMgcHVibGljYXRpb24gZmlsZXMuCgpgYGB7cn0KZmlsZV93b3MgPC0gIndvc18yMDE4XzIwMjMuYmliIgpmaWxlX3Njb3B1cyA8LSAic2NvcHVzXzIwMThfMjAyNC5iaWIiCk1fd29zIDwtIGNvbnZlcnQyZGYoZmlsZSA9IGZpbGVfd29zLCBkYnNvdXJjZSA9ICJ3b3MiLCBmb3JtYXQgPSAiYmlidGV4IikKTV9zY29wdXMgPC0gY29udmVydDJkZihmaWxlID0gZmlsZV9zY29wdXMsIGRic291cmNlID0gInNjb3B1cyIsIGZvcm1hdCA9ICJiaWJ0ZXgiKQpgYGAKCkZpcnN0IGJpYmxpb21ldHJpYyBhbmFseXNpczoKYGBge3J9CnJlc3VsdHNfd29zIDwtIGJpYmxpb0FuYWx5c2lzKE1fd29zLCBzZXAgPSAiOyIpCnJlc3VsdHNfc2NvcHVzIDwtIGJpYmxpb0FuYWx5c2lzKE1fc2NvcHVzLCBzZXAgPSAiOyIpCndyaXRlLmNzdihyZXN1bHRzX3dvcyRTb3VyY2VzLCAic291cmNlc193b3MuY3N2Iiwgcm93Lm5hbWVzPUZBTFNFKQp3cml0ZS5jc3YocmVzdWx0c19zY29wdXMkU291cmNlcywgInNvdXJjZXNfc2NvcHVzLmNzdiIsIHJvdy5uYW1lcz1GQUxTRSkKYGBgCgpCYXNpYyBwbG90cyBmb3IgV29TIGRhdGEuCmBgYHtyfQpwbG90KHggPSByZXN1bHRzX3dvcywgayA9IDEwLCBwYXVzZSA9IEZBTFNFKQpgYGAKQmFzaWMgcGxvdHMgZm9yIFNjb3B1cyBkYXRhLgpgYGB7cn0KcGxvdCh4ID0gcmVzdWx0c19zY29wdXMsIGsgPSAxMCwgcGF1c2UgPSBGQUxTRSkKYGBgClNvbWUgY2l0YXRpb24gYW5hbHlzaXMgd2l0aCBXb1MgZGF0YS4KYGBge3J9CkNSIDwtIGNpdGF0aW9ucyhNX3dvcywgZmllbGQgPSAiYXJ0aWNsZSIsIHNlcCA9ICI7IikKY2JpbmQoQ1IkQ2l0ZWRbMToxMF0pCkEgPC0gY29jTWF0cml4KE1fd29zLCBGaWVsZCA9ICJTTyIsIHNlcCA9ICI7IikKc29ydChNYXRyaXg6OmNvbFN1bXMoQSksIGRlY3JlYXNpbmcgPSBUUlVFKVsxOjEwXQpgYGAKCmBgYHtyfQpBIDwtIGNvY01hdHJpeChNX3dvcywgRmllbGQgPSAiQ1IiLCBzZXAgPSAiLiAgIikKc29ydChNYXRyaXg6OmNvbFN1bXMoQSksIGRlY3JlYXNpbmcgPSBUUlVFKVsxOjEwXQpgYGAKVGhlIG1haW4gc291cmNlcyBmb3IgcHVibGljYXRpb24gYWNjb3JkaW5nIHRvIFdvUyBkYXRhOgpgYGB7cn0KZGF0YS50YWJsZShyZXN1bHRzX3dvcyRTb3VyY2VzKQpgYGAKVGhlIG1haW4gc291cmNlcyBmb3IgcHVibGljYXRpb24gYWNjb3JkaW5nIHRvIFNjb3B1cyBkYXRhOgpgYGB7cn0KZGF0YS50YWJsZShyZXN1bHRzX3Njb3B1cyRTb3VyY2VzKQpgYGAKCkNyZWF0ZSBrZXl3b3JkIGNvLW9jY3VycmVuY2VzIG5ldHdvcmsgd2l0aCBXb1MgZGF0YToKYGBge3J9Ck5ldE1hdHJpeCA8LSBiaWJsaW9OZXR3b3JrKE1fd29zLCBhbmFseXNpcyA9ICJjby1vY2N1cnJlbmNlcyIsIG5ldHdvcmsgPSAia2V5d29yZHMiLCBzZXAgPSAiOyIpCiMgUGxvdCB0aGUgbmV0d29yawpuZXQ9bmV0d29ya1Bsb3QoTmV0TWF0cml4LCBub3JtYWxpemU9ImFzc29jaWF0aW9uIiwgd2VpZ2h0ZWQ9VCwgbiA9IDI1LCBUaXRsZSA9ICJXb1MgS2V5d29yZCBDby1vY2N1cnJlbmNlcyIsIHR5cGUgPSAiZnJ1Y2h0ZXJtYW4iLCBzaXplPVQsIGVkZ2VzaXplID0gNCxsYWJlbHNpemU9MS4wLGNvbW11bml0eS5yZXB1bHNpb24gPSAwLjEsc2l6ZS5jZXggPSBULGhhbG8gPSBGKQpgYGAKQ3JlYXRlIGtleXdvcmQgY28tb2NjdXJyZW5jZXMgbmV0d29yayB3aXRoIFNjb3B1cyBkYXRhOgpgYGB7cn0KTmV0TWF0cml4IDwtIGJpYmxpb05ldHdvcmsoTV9zY29wdXMsIGFuYWx5c2lzID0gImNvLW9jY3VycmVuY2VzIiwgbmV0d29yayA9ICJrZXl3b3JkcyIsIHNlcCA9ICI7IikKIyBQbG90IHRoZSBuZXR3b3JrCm5ldD1uZXR3b3JrUGxvdChOZXRNYXRyaXgsIG5vcm1hbGl6ZT0iYXNzb2NpYXRpb24iLCB3ZWlnaHRlZD1ULCBuID0gMjAsIFRpdGxlID0gIlNjb3B1cyBLZXl3b3JkIENvLW9jY3VycmVuY2VzIiwgdHlwZSA9ICJmcnVjaHRlcm1hbiIsIHNpemU9VCwgZWRnZXNpemUgPSA0LGxhYmVsc2l6ZT0xLjAsY29tbXVuaXR5LnJlcHVsc2lvbiA9IDAuMSxzaXplLmNleCA9IFQsaGFsbyA9IEYpCmBgYAoKQ3JlYXRlIGNsYXNzaWNhbCBhcnRpY2xlIGNvdXBsaW5nIG5ldHdvcmsgd2l0aCBXb1MgZGF0YToKYGBge3J9Ck5ldE1hdHJpeCA8LSBiaWJsaW9OZXR3b3JrKE1fd29zLCBhbmFseXNpcyA9ICJjb3VwbGluZyIsIG5ldHdvcmsgPSAicmVmZXJlbmNlcyIsIHNlcCA9ICI7IikKIyBQbG90IHRoZSBuZXR3b3JrCm5ldD1uZXR3b3JrUGxvdChOZXRNYXRyaXgsICBub3JtYWxpemUgPSAic2FsdG9uIiwgd2VpZ2h0ZWQ9TlVMTCwgbiA9IDMwLCBUaXRsZSA9ICJXb1MgQXJ0aWNsZScgQ291cGxpbmciLCB0eXBlID0gImZydWNodGVybWFuIiwgc2l6ZT0xMCxzaXplLmNleD1ULHJlbW92ZS5tdWx0aXBsZT1UUlVFLGxhYmVsc2l6ZT0xLjAsbGFiZWwubj0yMCxsYWJlbC5jZXg9RikKYGBgCkNyZWF0ZSBhdXRob3JzJyBjb3VwbGluZyBuZXR3b3JrIHdpdGggV29TIGRhdGE6CmBgYHtyfQpOZXRNYXRyaXggPC0gYmlibGlvTmV0d29yayhNX3dvcywgYW5hbHlzaXMgPSAiY291cGxpbmciLCBuZXR3b3JrID0gImF1dGhvcnMiLCBzZXAgPSAiOyIpCm5ldD1uZXR3b3JrUGxvdChOZXRNYXRyaXgsICBub3JtYWxpemUgPSAic2FsdG9uIiwgd2VpZ2h0ZWQ9VCwgbiA9IDIwLCBUaXRsZSA9ICJXb1MgQXV0aG9ycycgQ291cGxpbmciLCB0eXBlID0gImZydWNodGVybWFuIiwgc2l6ZSA9IDUsc2l6ZS5jZXg9VCxyZW1vdmUubXVsdGlwbGU9VFJVRSxsYWJlbHNpemU9Mi4wLGxhYmVsLm49MjAsbGFiZWwuY2V4ID0gVCkKYGBgCkNvbmNlcHR1YWwgU3RydWN0dXJlIHVzaW5nIGtleXdvcmRzIChtZXRob2Q9IkNBIikgd2l0aCBXb1MgZGF0YToKYGBge3J9Cm9wdGlvbnMoZ2dyZXBlbC5tYXgub3ZlcmxhcHMgPSBJbmYpCkNTIDwtIGNvbmNlcHR1YWxTdHJ1Y3R1cmUoTV93b3MsZmllbGQ9IklEIiwgbWV0aG9kPSJDQSIsIG1pbkRlZ3JlZT00LCBjbHVzdD01LCBzdGVtbWluZz1GQUxTRSwgbGFiZWxzaXplPTEwLCBkb2N1bWVudHM9MTApCmBgYApDb25jZXB0dWFsIFN0cnVjdHVyZSB1c2luZyBrZXl3b3JkcyAobWV0aG9kPSJDQSIpIHdpdGggU2NvcHVzIGRhdGE6CmBgYHtyfQpDUyA8LSBjb25jZXB0dWFsU3RydWN0dXJlKE1fc2NvcHVzLGZpZWxkPSJJRCIsIG1ldGhvZD0iQ0EiLCBtaW5EZWdyZWU9NCwgY2x1c3Q9NSwgc3RlbW1pbmc9RkFMU0UsIGxhYmVsc2l6ZT0xMCwgZG9jdW1lbnRzPTEwKQpgYGAKQ3JlYXRlIGEgaGlzdG9yaWNhbCBjaXRhdGlvbiBuZXR3b3JrIHdpdGggV29TIGRhdGE6CmBgYHtyfQpoaXN0UmVzdWx0cyA8LSBoaXN0TmV0d29yayhNX3dvcywgbWluLmNpdGF0aW9ucyA9IDEsIHNlcCA9ICI7IikKIyBQbG90IGEgaGlzdG9yaWNhbCBjby1jaXRhdGlvbiBuZXR3b3JrCm9wdGlvbnMocmVwci5wbG90LndpZHRoID0gMTAsIHJlcHIucGxvdC5oZWlnaHQgPTIwKSAKcG5nKGZpbGVuYW1lPSJoaXN0TmV0d29yay5wbmciLCB3aWR0aD0xMDAwLCBoZWlnaHQ9MTAwMCkKbmV0IDwtIGhpc3RQbG90KGhpc3RSZXN1bHRzLCBuPTUwLCBzaXplID0gNCwgbGFiZWxzaXplPTQpCmRldi5vZmYoKQpgYGAKIVtUaGUgcmVzdWx0aW5nIGhpc3RvcmljYWwgbmV0d29ya10oaGlzdE5ldHdvcmsucG5nKQoKUmVhZCB0aGUgc3lub255bSBhbmQgaWdub3JlZCBrZXl3b3JkcyBmaWxlcy4KYGBge3J9CiNzeW5vbnltc19maWxlIDwtIHJlYWQuY3N2KCJzeW5vbnltcy5jc3YiKQpzeW5vbnltc19maWxlIDwtIHNjYW4oInN5bm9ueW1zLmNzdiIsc2VwPSdcbicsIHdoYXQgPSAiIiwgcXVpZXQgPSBUUlVFKQpzeW5vbnltc19maWxlIDwtIGdzdWIoIiwiLCAiOyAiLCBzeW5vbnltc19maWxlKQpzeW5vbnltc19maWxlIDwtIGMoc3lub255bXNfZmlsZSkKcmVtb3ZlX2ZpbGUgPC0gc2NhbigicmVtb3ZlLmNzdiIsc2VwPSdcbicsIHdoYXQgPSAiIiwgcXVpZXQgPSBUUlVFKQpyZW1vdmVfZmlsZSA8LSByZW1vdmVfZmlsZQpgYGAKCk5vdywgY3JlYXRlIHRoZSB0aGVtYXRpYyBtYXAgdXNpbmcgdGhlIHN5bm9ueW1zIHdpdGggV29TIGRhdGE6CmBgYHtyfQpyZXMgPC0gdGhlbWF0aWNNYXAoTV93b3MsIGZpZWxkID0gIklEIiwgbiA9IDI1MCwgbWluZnJlcSA9IDUsIHNpemUgPSAwLjUsIHJlcGVsID0gVFJVRSwgc3lub255bXMgPSBzeW5vbnltc19maWxlLCByZW1vdmUudGVybXMgPSByZW1vdmVfZmlsZSkKcGxvdChyZXMkbWFwKQpgYGAKCk5vdywgY3JlYXRlIHRoZSB0aGVtYXRpYyBtYXAgdXNpbmcgdGhlIHN5bm9ueW1zIGFuZCB0aGUgYXV0aG9yJ3Mga2V5d29yZHMgd2l0aCBXb1MgZGF0YToKYGBge3J9CnJlcyA8LSB0aGVtYXRpY01hcChNX3dvcywgZmllbGQgPSAiREUiLCBuID0gMjUwLCBtaW5mcmVxID0gNSwgc2l6ZSA9IDAuNSwgcmVwZWwgPSBUUlVFLCBzeW5vbnltcyA9IHN5bm9ueW1zX2ZpbGUsIHJlbW92ZS50ZXJtcyA9IHJlbW92ZV9maWxlKQpwbG90KHJlcyRtYXApCmBgYAoKVGhlIHNhbWUgYnV0IHdpdGggdGhlIFNjb3B1cyBkYXRhOgpgYGB7cn0KcmVzIDwtIHRoZW1hdGljTWFwKE1fc2NvcHVzLCBmaWVsZCA9ICJJRCIsIG4gPSAyNTAsIG1pbmZyZXEgPSA1LCBzaXplID0gMC41LCByZXBlbCA9IFRSVUUsIHN5bm9ueW1zID0gc3lub255bXNfZmlsZSwgcmVtb3ZlLnRlcm1zID0gcmVtb3ZlX2ZpbGUpCnBsb3QocmVzJG1hcCkKYGBgCgpUaGUgc2FtZSBidXQgd2l0aCB0aGUgU2NvcHVzIGRhdGEgYW5kIHRoZSBhdXRob3IncyBrZXl3b3JkczoKYGBge3J9CnJlcyA8LSB0aGVtYXRpY01hcChNX3Njb3B1cywgZmllbGQgPSAiREUiLCBuID0gMjUwLCBtaW5mcmVxID0gNSwgc2l6ZSA9IDAuNSwgcmVwZWwgPSBUUlVFLCBzeW5vbnltcyA9IHN5bm9ueW1zX2ZpbGUsIHJlbW92ZS50ZXJtcyA9IHJlbW92ZV9maWxlKQpwbG90KHJlcyRtYXApCmBgYAoKV2UgYWRkIHRoZSBmdW5jdGlvbiB0byBjcmVhdGUgd29yZGxpc3RzLgoKYGBge3J9CndvcmRsaXN0IDwtIGZ1bmN0aW9uKE0sIEZpZWxkLCBuLCBtZWFzdXJlLCBuZ3JhbXMsIHJlbW92ZS50ZXJtcz1OVUxMLCBzeW5vbnltcz1OVUxMKXsKICBzd2l0Y2goRmllbGQsCiAgICAgICAgIElEPXt2PXRhYmxlVGFnKE0sIklEIiwgcmVtb3ZlLnRlcm1zICA9IHJlbW92ZS50ZXJtcywgc3lub255bXMgPSBzeW5vbnltcyl9LAogICAgICAgICBERT17dj10YWJsZVRhZyhNLCJERSIsIHJlbW92ZS50ZXJtcyA9IHJlbW92ZS50ZXJtcywgc3lub255bXMgPSBzeW5vbnltcyl9LAogICAgICAgICBUST17CiAgICAgICAgICAgaWYgKCEoIlRJX1RNIiAlaW4lIG5hbWVzKE0pKSl7CiAgICAgICAgICAgICB2PXRhYmxlVGFnKE0sIlRJIiwgbmdyYW1zPW5ncmFtcywgcmVtb3ZlLnRlcm1zPXJlbW92ZS50ZXJtcywgc3lub255bXMgPSBzeW5vbnltcykKICAgICAgICAgICAgIAogICAgICAgICAgIH19LAogICAgICAgICBBQj17aWYgKCEoIkFCX1RNIiAlaW4lIG5hbWVzKE0pKSl7CiAgICAgICAgICAgdj10YWJsZVRhZyhNLCJBQiIsIG5ncmFtcz1uZ3JhbXMsIHJlbW92ZS50ZXJtcyA9IHJlbW92ZS50ZXJtcywgc3lub255bXMgPSBzeW5vbnltcykKICAgICAgICAgfX0sCiAgICAgICAgIFdDPXsKICAgICAgICAgICB2PXRhYmxlVGFnKE0sIldDIikKICAgICAgICAgfQogICkKICBuYW1lcyh2KT10b2xvd2VyKG5hbWVzKHYpKQogICN2PXRhYmxlVGFnKHZhbHVlcyRNLCJJRCIpCiAgbj1taW4oYyhuLGxlbmd0aCh2KSkpCiAgV29yZHM9ZGF0YS5mcmFtZShUZXJtcz1uYW1lcyh2KVsxOm5dLCBGcmVxdWVuY3k9KGFzLm51bWVyaWModilbMTpuXSksIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKICBXPVdvcmRzCiAgc3dpdGNoKG1lYXN1cmUsCiAgICAgICAgIGlkZW50aXR5PXt9LAogICAgICAgICBzcXJ0PXtXJEZyZXF1ZW5jeT1zcXJ0KFckRnJlcXVlbmN5KX0sCiAgICAgICAgIGxvZz17VyRGcmVxdWVuY3k9bG9nKFckRnJlcXVlbmN5KzEpfSwKICAgICAgICAgbG9nMTA9e1ckRnJlcXVlbmN5PWxvZzEwKFckRnJlcXVlbmN5KzEpfQogICkKICAKICByZXN1bHRzPWxpc3Qodj12LFc9VywgV29yZHM9V29yZHMpCiAgcmV0dXJuKHJlc3VsdHMpCn0KYGBgCgoKYGBge3J9CnJlc1cgPC0gd29yZGxpc3QoTT1NX3dvcywgRmllbGQ9IklEIiwgbj0xNTAsIG1lYXN1cmU9ImlkZW50aXR5IiwgbmdyYW1zPTEsIHN5bm9ueW1zID0gc3lub255bXNfZmlsZSwgcmVtb3ZlLnRlcm1zID0gcmVtb3ZlX2ZpbGUpClcgPC0gcmVzVyRXCndyaXRlLmNzdihyZXNXW1siVyJdXSwgImRhdGFfd29zLmNzdiIsIHJvdy5uYW1lcz1GQUxTRSkKV29yZHMgPC0gcmVzVyRXb3Jkcwp3MSA8LSB3b3JkY2xvdWQyOjp3b3JkY2xvdWQyKFcsIHNpemUgPSAxLjUsIG1pblJvdGF0aW9uID0gMCwgbWF4Um90YXRpb24gPSAwLCByb3RhdGVSYXRpbyA9IDEpI21pblJvdGF0aW9uID0gLXBpLzIsIG1heFJvdGF0aW9uID0gLXBpLzIpCnNhdmVXaWRnZXQodzEsICd3MS5odG1sJywgc2VsZmNvbnRhaW5lZCA9IFQpCmBgYAoKV29yZGNsb3VkIHdpdGggV29TIGFuZCBrZXl3b3JkcyBwbHVzLgo8aWZyYW1lIHNyYyA9ICJ3MS5odG1sIiB3aWR0aCA9ICIxMDAwIiBoZWlnaHQgPSAiMTAwMCI+PC9pZnJhbWU+IAoKCmBgYHtyfQpyZXNXIDwtIHdvcmRsaXN0KE09TV93b3MsIEZpZWxkPSJERSIsIG49MTUwLCBtZWFzdXJlPSJpZGVudGl0eSIsIG5ncmFtcz0xLCByZW1vdmUudGVybXMgPSByZW1vdmVfZmlsZSwgc3lub255bXMgPSBzeW5vbnltc19maWxlKQpXIDwtIHJlc1ckVwp3cml0ZS5jc3YocmVzV1tbIlciXV0sICJkYXRhX3dvc19kZS5jc3YiLCByb3cubmFtZXM9RkFMU0UpCldvcmRzIDwtIHJlc1ckV29yZHMKdzIgPC0gd29yZGNsb3VkMjo6d29yZGNsb3VkMihXLCBzaXplID0gMS41LCBtaW5Sb3RhdGlvbiA9IDAsIG1heFJvdGF0aW9uID0gMCwgcm90YXRlUmF0aW8gPSAxKSNtaW5Sb3RhdGlvbiA9IC1waS8yLCBtYXhSb3RhdGlvbiA9IC1waS8yKQpzYXZlV2lkZ2V0KHcyLCAndzIuaHRtbCcsIHNlbGZjb250YWluZWQgPSBUKQpgYGAKCldvcmRjbG91ZCB3aXRoIFdvUyBhbmQgYXV0aG9yJ3Mga2V5d29yZHMuCjxpZnJhbWUgc3JjID0gIncyLmh0bWwiIHdpZHRoID0gIjEwMDAiIGhlaWdodCA9ICIxMDAwIj48L2lmcmFtZT4gCgoKYGBge3J9CnJlc1cgPC0gd29yZGxpc3QoTT1NX3Njb3B1cywgRmllbGQ9IklEIiwgbj0xNTAsIG1lYXN1cmU9ImlkZW50aXR5IiwgbmdyYW1zPTEsIHJlbW92ZS50ZXJtcyA9IHJlbW92ZV9maWxlLCBzeW5vbnltcyA9IHN5bm9ueW1zX2ZpbGUpClcgPC0gcmVzVyRXCndyaXRlLmNzdihyZXNXW1siVyJdXSwgImRhdGFfc2NvcHVzLmNzdiIsIHJvdy5uYW1lcz1GQUxTRSkKV29yZHMgPC0gcmVzVyRXb3Jkcwp3MyA8LSB3b3JkY2xvdWQyOjp3b3JkY2xvdWQyKFcsIHNpemUgPSAxLjUsIGNvbG9yID0gJ3JhbmRvbS1kYXJrJywgbWluUm90YXRpb24gPSAwLCBtYXhSb3RhdGlvbiA9IDAsIHJvdGF0ZVJhdGlvID0gMSkKc2F2ZVdpZGdldCh3MywgJ3czLmh0bWwnLCBzZWxmY29udGFpbmVkID0gVCkKYGBgCgpXb3JkY2xvdWQgd2l0aCBTY29wdXMgYW5kIGtleXdvcmRzIHBsdXMuCjxpZnJhbWUgc3JjID0gInczLmh0bWwiIHdpZHRoID0gIjEwMDAiIGhlaWdodCA9ICIxMDAwIj48L2lmcmFtZT4gCgpgYGB7cn0KcmVzVyA8LSB3b3JkbGlzdChNPU1fc2NvcHVzLCBGaWVsZD0iREUiLCBuPTE1MCwgbWVhc3VyZT0iaWRlbnRpdHkiLCBuZ3JhbXM9MSwgcmVtb3ZlLnRlcm1zID0gcmVtb3ZlX2ZpbGUsIHN5bm9ueW1zID0gc3lub255bXNfZmlsZSkKVyA8LSByZXNXJFcKd3JpdGUuY3N2KHJlc1dbWyJXIl1dLCAiZGF0YV9zY29wdXNfZGUuY3N2Iiwgcm93Lm5hbWVzPUZBTFNFKQpXb3JkcyA8LSByZXNXJFdvcmRzCnc0IDwtIHdvcmRjbG91ZDI6OndvcmRjbG91ZDIoVywgc2l6ZSA9IDEuNSwgY29sb3IgPSAncmFuZG9tLWRhcmsnLCBtaW5Sb3RhdGlvbiA9IDAsIG1heFJvdGF0aW9uID0gMCwgcm90YXRlUmF0aW8gPSAxKQpzYXZlV2lkZ2V0KHc0LCAndzQuaHRtbCcsIHNlbGZjb250YWluZWQgPSBUKQpgYGAKCldvcmRjbG91ZCB3aXRoIFNjb3B1cyBhbmQgYXV0aG9yJ3Mga2V5d29yZHMuCjxpZnJhbWUgc3JjID0gInc0Lmh0bWwiIHdpZHRoID0gIjEwMDAiIGhlaWdodCA9ICIxMDAwIj48L2lmcmFtZT4gCgpXZSBhcmUgZG9uZSEK